home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / cvs-1_3.lha / cvs-1.3 / src / mkmodules.c < prev    next >
C/C++ Source or Header  |  1992-03-31  |  9KB  |  393 lines

  1. /*
  2.  * Copyright (c) 1992, Brian Berliner and Jeff Polk
  3.  * Copyright (c) 1989-1992, Brian Berliner
  4.  * 
  5.  * You may distribute under the terms of the GNU General Public License as
  6.  * specified in the README file that comes with the CVS 1.3 kit.
  7.  * 
  8.  * mkmodules
  9.  * 
  10.  * Re-build the modules database for the CVS system.  Accepts one argument,
  11.  * which is the directory that the modules,v file lives in.
  12.  */
  13.  
  14. #include "cvs.h"
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "@(#)mkmodules.c 1.39 92/03/31";
  18. #endif
  19.  
  20. #ifndef DBLKSIZ
  21. #define    DBLKSIZ    4096            /* since GNU ndbm doesn't define it */
  22. #endif
  23.  
  24. char *program_name, *command_name;
  25.  
  26. char *Rcsbin = RCSBIN_DFLT;
  27. int noexec = 0;                /* Here only to satisfy use in subr.c */
  28. int trace = 0;                /* Here only to satisfy use in subr.c */
  29.  
  30. #if __STDC__
  31. static int checkout_file (char *file, char *temp);
  32. static void make_tempfile (char *temp);
  33. static void mkmodules_usage (void);
  34. static void rename_rcsfile (char *temp, char *real);
  35.  
  36. #ifndef MY_NDBM
  37. static void rename_dbmfile (char *temp);
  38. static void write_dbmfile (char *temp);
  39. #endif                /* !MY_NDBM */
  40.  
  41. #else                /* !__STDC__ */
  42.  
  43. static void make_tempfile ();
  44. static int checkout_file ();
  45. static void rename_rcsfile ();
  46. static void mkmodules_usage ();
  47.  
  48. #ifndef MY_NDBM
  49. static void write_dbmfile ();
  50. static void rename_dbmfile ();
  51. #endif                /* !MY_NDBM */
  52.  
  53. #endif                /* __STDC__ */
  54.  
  55. int
  56. main (argc, argv)
  57.     int argc;
  58.     char *argv[];
  59. {
  60.     extern char *getenv ();
  61.     char temp[PATH_MAX];
  62.     char *cp;
  63. #ifdef MY_NDBM
  64.     DBM *db;
  65. #endif
  66.  
  67.     /*
  68.      * Just save the last component of the path for error messages
  69.      */
  70.     if ((program_name = rindex (argv[0], '/')) == NULL)
  71.     program_name = argv[0];
  72.     else
  73.     program_name++;
  74.  
  75.     if (argc != 2)
  76.     mkmodules_usage ();
  77.  
  78.     if ((cp = getenv (RCSBIN_ENV)) != NULL)
  79.     Rcsbin = cp;
  80.  
  81.     /*
  82.      * If Rcsbin is set to something, make sure it is terminated with a slash
  83.      * character.  If not, add one.
  84.      */
  85.     if (Rcsbin[0] != '\0')
  86.     {
  87.     int len = strlen (Rcsbin);
  88.     char *rcsbin;
  89.  
  90.     if (Rcsbin[len - 1] != '/')
  91.     {
  92.         rcsbin = Rcsbin;
  93.         Rcsbin = xmalloc (len + 2);    /* one for '/', one for NULL */
  94.         (void) strcpy (Rcsbin, rcsbin);
  95.         (void) strcat (Rcsbin, "/");
  96.     }
  97.     }
  98.  
  99.     if (chdir (argv[1]) < 0)
  100.     error (1, errno, "cannot chdir to %s", argv[1]);
  101.  
  102.     /*
  103.      * First, do the work necessary to update the "modules" database.
  104.      */
  105.     make_tempfile (temp);
  106.     switch (checkout_file (CVSROOTADM_MODULES, temp))
  107.     {
  108.  
  109.     case 0:            /* everything ok */
  110. #ifdef MY_NDBM
  111.         /* open it, to generate any duplicate errors */
  112.         if ((db = dbm_open (temp, O_RDONLY, 0666)) != NULL)
  113.         dbm_close (db);
  114. #else
  115.         write_dbmfile (temp);
  116.         rename_dbmfile (temp);
  117. #endif
  118.         rename_rcsfile (temp, CVSROOTADM_MODULES);
  119.         break;
  120.  
  121.     case -1:            /* fork failed */
  122.         (void) unlink_file (temp);
  123.         exit (1);
  124.         /* NOTREACHED */
  125.  
  126.     default:
  127.         error (0, 0, 
  128.         "'cvs checkout' is less functional without a %s file",
  129.         CVSROOTADM_MODULES);
  130.         break;
  131.     }                    /* switch on checkout_file() */
  132.  
  133.     (void) unlink_file (temp);
  134.  
  135.     /*
  136.      * Now, check out the "loginfo" file, so that it is always up-to-date in
  137.      * the CVSROOT directory.
  138.      */
  139.     make_tempfile (temp);
  140.     if (checkout_file (CVSROOTADM_LOGINFO, temp) == 0)
  141.     rename_rcsfile (temp, CVSROOTADM_LOGINFO);
  142.     else
  143.     error (0, 0, 
  144.     "no logging of 'cvs commit' messages is done without a %s file",
  145.            CVSROOTADM_LOGINFO);
  146.     (void) unlink_file (temp);
  147.  
  148.     /*
  149.      * Now, check out the "rcsinfo" file, so that it is always up-to-date in
  150.      * the CVSROOT directory.
  151.      */
  152.     make_tempfile (temp);
  153.     if (checkout_file (CVSROOTADM_RCSINFO, temp) == 0)
  154.     rename_rcsfile (temp, CVSROOTADM_RCSINFO);
  155.     else
  156.     error (0, 0, 
  157.         "a %s file can be used to configure 'cvs commit' templates",
  158.         CVSROOTADM_RCSINFO);
  159.     (void) unlink_file (temp);
  160.  
  161.     /*
  162.      * Now, check out the "editinfo" file, so that it is always up-to-date in
  163.      * the CVSROOT directory.
  164.      */
  165.     make_tempfile (temp);
  166.     if (checkout_file (CVSROOTADM_EDITINFO, temp) == 0)
  167.     rename_rcsfile (temp, CVSROOTADM_EDITINFO);
  168.     else
  169.     error (0, 0, 
  170.            "a %s file can be used to validate log messages",
  171.            CVSROOTADM_EDITINFO);
  172.     (void) unlink_file (temp);
  173.  
  174.     /*
  175.      * Now, check out the "commitinfo" file, so that it is always up-to-date
  176.      * in the CVSROOT directory.
  177.      */
  178.     make_tempfile (temp);
  179.     if (checkout_file (CVSROOTADM_COMMITINFO, temp) == 0)
  180.     rename_rcsfile (temp, CVSROOTADM_COMMITINFO);
  181.     else
  182.     error (0, 0, 
  183.         "a %s file can be used to configure 'cvs commit' checking",
  184.         CVSROOTADM_COMMITINFO);
  185.     (void) unlink_file (temp);
  186.     return (0);
  187. }
  188.  
  189. /*
  190.  * Yeah, I know, there are NFS race conditions here.
  191.  */
  192. static void
  193. make_tempfile (temp)
  194.     char *temp;
  195. {
  196.     static int seed = 0;
  197.     int fd;
  198.  
  199.     if (seed == 0)
  200.     seed = getpid ();
  201.     while (1)
  202.     {
  203.     (void) sprintf (temp, "%s%d", BAKPREFIX, seed++);
  204.     if ((fd = open (temp, O_CREAT|O_EXCL|O_RDWR, 0666)) != -1)
  205.         break;
  206.     if (errno != EEXIST)
  207.         error (1, errno, "cannot create temporary file %s", temp);
  208.     }
  209.     if (close(fd) < 0)
  210.     error(1, errno, "cannot close temporary file %s", temp);
  211. }
  212.  
  213. static int
  214. checkout_file (file, temp)
  215.     char *file;
  216.     char *temp;
  217. {
  218.     char rcs[PATH_MAX];
  219.     int retcode = 0;
  220.  
  221.     (void) sprintf (rcs, "%s%s", file, RCSEXT);
  222.     if (!isfile (rcs))
  223.     return (1);
  224.     run_setup ("%s%s -q -p", Rcsbin, RCS_CO);
  225.     run_arg (rcs);
  226.     if ((retcode = run_exec (RUN_TTY, temp, RUN_TTY, RUN_NORMAL)) != 0)
  227.     {
  228.     error (0, retcode == -1 ? errno : 0, "failed to check out %s file", file);
  229.     }
  230.     return (retcode);
  231. }
  232.  
  233. #ifndef MY_NDBM
  234.  
  235. static void
  236. write_dbmfile (temp)
  237.     char *temp;
  238. {
  239.     char line[DBLKSIZ], value[DBLKSIZ];
  240.     FILE *fp;
  241.     DBM *db;
  242.     char *cp, *vp;
  243.     datum key, val;
  244.     int len, cont, err = 0;
  245.  
  246.     fp = open_file (temp, "r");
  247.     if ((db = dbm_open (temp, O_RDWR | O_CREAT | O_TRUNC, 0666)) == NULL)
  248.     error (1, errno, "cannot open dbm file %s for creation", temp);
  249.     for (cont = 0; fgets (line, sizeof (line), fp) != NULL;)
  250.     {
  251.     if ((cp = rindex (line, '\n')) != NULL)
  252.         *cp = '\0';            /* strip the newline */
  253.  
  254.     /*
  255.      * Add the line to the value, at the end if this is a continuation
  256.      * line; otherwise at the beginning, but only after any trailing
  257.      * backslash is removed.
  258.      */
  259.     vp = value;
  260.     if (cont)
  261.         vp += strlen (value);
  262.  
  263.     /*
  264.      * See if the line we read is a continuation line, and strip the
  265.      * backslash if so.
  266.      */
  267.     len = strlen (line);
  268.     if (len > 0)
  269.         cp = &line[len - 1];
  270.     else
  271.         cp = line;
  272.     if (*cp == '\\')
  273.     {
  274.         cont = 1;
  275.         *cp = '\0';
  276.     }
  277.     else
  278.     {
  279.         cont = 0;
  280.     }
  281.     (void) strcpy (vp, line);
  282.     if (value[0] == '#')
  283.         continue;            /* comment line */
  284.     vp = value;
  285.     while (*vp && isspace (*vp))
  286.         vp++;
  287.     if (*vp == '\0')
  288.         continue;            /* empty line */
  289.  
  290.     /*
  291.      * If this was not a continuation line, add the entry to the database
  292.      */
  293.     if (!cont)
  294.     {
  295.         key.dptr = vp;
  296.         while (*vp && !isspace (*vp))
  297.         vp++;
  298.         key.dsize = vp - key.dptr;
  299.         *vp++ = '\0';        /* NULL terminate the key */
  300.         while (*vp && isspace (*vp))
  301.         vp++;            /* skip whitespace to value */
  302.         if (*vp == '\0')
  303.         {
  304.         error (0, 0, "warning: NULL value for key `%s'", key.dptr);
  305.         continue;
  306.         }
  307.         val.dptr = vp;
  308.         val.dsize = strlen (vp);
  309.         if (dbm_store (db, key, val, DBM_INSERT) == 1)
  310.         {
  311.         error (0, 0, "duplicate key found for `%s'", key.dptr);
  312.         err++;
  313.         }
  314.     }
  315.     }
  316.     dbm_close (db);
  317.     (void) fclose (fp);
  318.     if (err)
  319.     {
  320.     char dotdir[50], dotpag[50];
  321.  
  322.     (void) sprintf (dotdir, "%s.dir", temp);
  323.     (void) sprintf (dotpag, "%s.pag", temp);
  324.     (void) unlink_file (dotdir);
  325.     (void) unlink_file (dotpag);
  326.     error (1, 0, "DBM creation failed; correct above errors");
  327.     }
  328. }
  329.  
  330. static void
  331. rename_dbmfile (temp)
  332.     char *temp;
  333. {
  334.     char newdir[50], newpag[50];
  335.     char dotdir[50], dotpag[50];
  336.     char bakdir[50], bakpag[50];
  337.  
  338.     (void) sprintf (dotdir, "%s.dir", CVSROOTADM_MODULES);
  339.     (void) sprintf (dotpag, "%s.pag", CVSROOTADM_MODULES);
  340.     (void) sprintf (bakdir, "%s%s.dir", BAKPREFIX, CVSROOTADM_MODULES);
  341.     (void) sprintf (bakpag, "%s%s.pag", BAKPREFIX, CVSROOTADM_MODULES);
  342.     (void) sprintf (newdir, "%s.dir", temp);
  343.     (void) sprintf (newpag, "%s.pag", temp);
  344.  
  345.     (void) chmod (newdir, 0666);
  346.     (void) chmod (newpag, 0666);
  347.  
  348.     /* don't mess with me */
  349.     SIG_beginCrSect ();
  350.  
  351.     (void) unlink_file (bakdir);    /* rm .#modules.dir .#modules.pag */
  352.     (void) unlink_file (bakpag);
  353.     (void) rename (dotdir, bakdir);    /* mv modules.dir .#modules.dir */
  354.     (void) rename (dotpag, bakpag);    /* mv modules.pag .#modules.pag */
  355.     (void) rename (newdir, dotdir);    /* mv "temp".dir modules.dir */
  356.     (void) rename (newpag, dotpag);    /* mv "temp".pag modules.pag */
  357.  
  358.     /* OK -- make my day */
  359.     SIG_endCrSect ();
  360. }
  361.  
  362. #endif                /* !MY_NDBM */
  363.  
  364. static void
  365. rename_rcsfile (temp, real)
  366.     char *temp;
  367.     char *real;
  368. {
  369.     char bak[50];
  370.  
  371.     if (chmod (temp, 0444) < 0)        /* chmod 444 "temp" */
  372.     error (0, errno, "warning: cannot chmod %s", temp);
  373.     (void) sprintf (bak, "%s%s", BAKPREFIX, real);
  374.     (void) unlink_file (bak);        /* rm .#loginfo */
  375.     (void) rename (real, bak);        /* mv loginfo .#loginfo */
  376.     (void) rename (temp, real);        /* mv "temp" loginfo */
  377. }
  378.  
  379. /*
  380.  * For error() only
  381.  */
  382. void
  383. Lock_Cleanup ()
  384. {
  385. }
  386.  
  387. static void
  388. mkmodules_usage ()
  389. {
  390.     (void) fprintf (stderr, "Usage: %s modules-directory\n", program_name);
  391.     exit (1);
  392. }
  393.